/*
 * Copyright 2010 Alessandro Bellucci
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.soupframework.gwt.designerpanel.demos.client;

import org.soupframework.gwt.designerpanel.client.DesignerPanel;
import org.soupframework.gwt.designerpanel.client.command.impl.CommandFactoryImpl;
import org.soupframework.gwt.designerpanel.client.decorator.impl.BorderWidgetDecorator;
import org.soupframework.gwt.designerpanel.client.decorator.impl.ResizePointsWidgetDecorator;
import org.soupframework.gwt.designerpanel.client.designer.ContainerDesigner;
import org.soupframework.gwt.designerpanel.client.designer.DesignerManager;
import org.soupframework.gwt.designerpanel.client.designer.OperatingMode;
import org.soupframework.gwt.designerpanel.client.designer.impl.widget.WidgetDesignerManagerFactory;
import org.soupframework.gwt.designerpanel.client.dragproxy.impl.SimpleDragProxyFactory;
import org.soupframework.gwt.designerpanel.client.event.ObjectAddedEvent;
import org.soupframework.gwt.designerpanel.client.event.ObjectAddedEventHandler;
import org.soupframework.gwt.designerpanel.client.grid.Grid;
import org.soupframework.gwt.designerpanel.client.grid.GridMode;
import org.soupframework.gwt.designerpanel.client.grid.impl.DivBasedGrid;
import org.soupframework.gwt.designerpanel.client.interaction.InteractionMode;
import org.soupframework.gwt.designerpanel.client.interaction.NewObjectsHandler;
import org.soupframework.gwt.designerpanel.interaction.keyboard.client.KeyboardInteractionHandlerManager;
import org.soupframework.gwt.designerpanel.interaction.mouse.client.MouseInteractionHandlerManager;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.dom.client.Style.BorderStyle;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CaptionPanel;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.StackPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class DesignerPanelSimpleDemo implements EntryPoint {

	public DesignerPanelSimpleDemo() {
	}

	public void onModuleLoad() {
		showDemo();
	}

	public static native String getMobileUserAgent() /*-{
		var ua = navigator.userAgent.toLowerCase();
		if (ua.indexOf("webkit") != -1 && ua.indexOf("mobile") != -1) {
			return "mobilesafari";
		}
		return "none";
	}-*/;

	private DesignerManager<Widget> demoDesignerManager;
	private MouseInteractionHandlerManager<Widget> mouseInteractionHandlerManager;
	private KeyboardInteractionHandlerManager<Widget> keyboardInteractionHandlerManager;
	private ToggleButtonGroup widgetPalette;
	private NewObjectsHandler<Widget> newWidgetsHandler;

	public void showDemo() {
		final Widget widgetPalettePanel = createWidgetPalette();

		final AbsolutePanel mainPanel = new AbsolutePanel();
		mainPanel.setPixelSize(800, 600);
		mainPanel.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);
		mainPanel.getElement().getStyle().setBorderWidth(1, Unit.PX);

		final DesignerPanel<Widget> designerPanel = new DesignerPanel<Widget>(mainPanel, new WidgetDesignerManagerFactory());
		designerPanel.setPixelSize(800, 600);
		demoDesignerManager = designerPanel.getDesignerManager();
		demoDesignerManager.setOperatingMode(OperatingMode.DESIGN_MODE);
		demoDesignerManager.setCommandFactory(new CommandFactoryImpl<Widget>());
		demoDesignerManager.setContextMenuFactory(new ContextMenuFactoryImpl<Widget>());
		demoDesignerManager.enableHistory();
		demoDesignerManager.setObjectHighlighter(new BorderWidgetDecorator<Widget>(BorderStyle.DASHED, 1, "#0000FF"));
		demoDesignerManager.setContainerDesignModeDecorator(new BorderWidgetDecorator<Widget>(BorderStyle.SOLID, 1, "#BBBB00"));
		demoDesignerManager.setDragProxyFactory(new SimpleDragProxyFactory<Widget>("#8888EE", "#0000EE"));
		demoDesignerManager.setResizePointsDecorator(new ResizePointsWidgetDecorator<Widget>(BorderStyle.DASHED, 1, "#0000FF"));
		final ContainerDesigner<Widget> demoDesigner = (ContainerDesigner<Widget>)demoDesignerManager.getRootDesigner();

		final Grid grid = new DivBasedGrid(800, 600, 15, 15);
		designerPanel.setGrid(grid);

		this.mouseInteractionHandlerManager = MouseInteractionHandlerManager.createInteractionHandlerManager(demoDesignerManager);
		this.mouseInteractionHandlerManager.setNewWidgetsHandler(this.newWidgetsHandler);
		this.mouseInteractionHandlerManager.setInteractionMode(InteractionMode.SELECT);

		this.keyboardInteractionHandlerManager = KeyboardInteractionHandlerManager.createInteractionHandlerManager(demoDesignerManager);
		this.keyboardInteractionHandlerManager.setInteractionMode(InteractionMode.SELECT);

		// One widget is added at a time
		demoDesigner.addObjectAddedHandler(new ObjectAddedEventHandler<Widget>() {
			@Override
			public void onObjectAdded(ObjectAddedEvent<Widget> event) {
				widgetPalette.clearSelection();
			}
		});


		HorizontalPanel actionsPanel = new HorizontalPanel();
		actionsPanel.setSpacing(2);
		final Button clearButton = new Button("Clear panel");
		clearButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				if(Window.confirm("This action will erase the panel,continue?")){
					demoDesigner.clear();
				}
			}
		});
		PushButton undoButton = new PushButton(new Image("images/Undo-icon-16.png"));
		undoButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				demoDesignerManager.undo();
			}
		});
		actionsPanel.add(undoButton);
		PushButton redoButton = new PushButton(new Image("images/Redo-icon-16.png"));
		redoButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				demoDesignerManager.redo();
			}
		});
		actionsPanel.add(redoButton);
		actionsPanel.add(clearButton);
		actionsPanel.add(new Label("Operating mode: "));
		final RadioButton designModeButton = new RadioButton("designMode", "Design Mode");
		///designModeButton.getElement().getStyle().setBackgroundColor("#CC0000");
		designModeButton.setValue(true);
		final RadioButton liveDesignModeButton = new RadioButton("designMode", "Live Design Mode");
		//liveDesignModeButton.getElement().getStyle().setBackgroundColor("#DDDD00");
		final RadioButton liveModeButton = new RadioButton("designMode", "Live Mode");
		//liveModeButton.getElement().getStyle().setBackgroundColor("#00CC00");
		ClickHandler clickHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				RadioButton source = (RadioButton)event.getSource();
				if(source == designModeButton){
					demoDesignerManager.setOperatingMode(OperatingMode.DESIGN_MODE);
				}
				else if(source == liveDesignModeButton){
					demoDesignerManager.setOperatingMode(OperatingMode.LIVE_DESIGN_MODE);
				}
				else if(source == liveModeButton){
					demoDesignerManager.setOperatingMode(OperatingMode.LIVE_MODE);
				}
			}
		};
		designModeButton.addClickHandler(clickHandler);
		liveDesignModeButton.addClickHandler(clickHandler);
		liveModeButton.addClickHandler(clickHandler);
		actionsPanel.add(designModeButton);
		actionsPanel.add(liveDesignModeButton);
		actionsPanel.add(liveModeButton);

		// grid controls
		CheckBox showGridCheckBox = new CheckBox("Show grid");
		showGridCheckBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
			@Override
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				if(event.getValue()){
					demoDesignerManager.showGrid();
				}
				else{
					demoDesignerManager.hideGrid();
				}
			}
		});

		CheckBox alignToGridCheckBox = new CheckBox("Align to grid");
		alignToGridCheckBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
			@Override
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				if(event.getValue()){
					demoDesignerManager.setGridMode(GridMode.AUTO_ALIGN);
				}
				else{
					demoDesignerManager.setGridMode(GridMode.MANUAL_ALIGN);
				}
			}
		});

		final com.google.gwt.user.client.ui.Grid gridCellSize = new com.google.gwt.user.client.ui.Grid (1, 4);
		gridCellSize.setCellSpacing(4);
		gridCellSize.setWidget(0, 0, new Label("Grid cell size"));
		final Label cellSizeLabel = new Label(grid.getCellWidth() + "x" + grid.getCellHeight());
		gridCellSize.setWidget(0, 2, cellSizeLabel);
		gridCellSize.getCellFormatter().setAlignment(0, 2, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE);
		gridCellSize.setWidget(0, 1, new Button("&lt;", new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				if(grid.getCellWidth() > 5){
					grid.setGridCellSize(grid.getCellWidth() - 5, grid.getCellHeight() - 5);
					cellSizeLabel.setText(grid.getCellWidth() + "x" + grid.getCellHeight());
				}
			}
		}));
		gridCellSize.getCellFormatter().setAlignment(0, 1, HasHorizontalAlignment.ALIGN_RIGHT, HasVerticalAlignment.ALIGN_MIDDLE);
		gridCellSize.setWidget(0, 3, new Button("&gt;", new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				if(grid.getCellWidth() < 95){
					grid.setGridCellSize(grid.getCellWidth() + 5, grid.getCellHeight() + 5);
					cellSizeLabel.setText(grid.getCellWidth() + "x" + grid.getCellHeight());
				}
			}
		}));
		gridCellSize.getCellFormatter().setAlignment(0, 3, HasHorizontalAlignment.ALIGN_LEFT, HasVerticalAlignment.ALIGN_MIDDLE);

		VerticalPanel optionsPanel = new VerticalPanel();
		optionsPanel.add(showGridCheckBox);
		optionsPanel.add(alignToGridCheckBox);
		optionsPanel.add(gridCellSize);

		final com.google.gwt.user.client.ui.Grid layout = new com.google.gwt.user.client.ui.Grid (2, 3);
		layout.setCellSpacing(15);
		layout.setWidget(0, 1, actionsPanel);
		layout.setWidget(1, 0, widgetPalettePanel);
		layout.getCellFormatter().setAlignment(1, 0, HasHorizontalAlignment.ALIGN_LEFT, HasVerticalAlignment.ALIGN_TOP);
		layout.setWidget(1, 1, designerPanel);
		layout.getCellFormatter().setAlignment(1, 2, HasHorizontalAlignment.ALIGN_LEFT, HasVerticalAlignment.ALIGN_TOP);
		layout.setWidget(1, 2, optionsPanel);

		RootPanel.get().add(layout);
	}

	private Widget createWidgetPalette() {
		StackPanel stackPanel = new StackPanel();
		stackPanel.setWidth("120px");

		final ToggleButton labelToggleButton = new ToggleButton("Label");
		final ToggleButton textboxToggleButton = new ToggleButton("TextBox");
		final ToggleButton buttonToggleButton = new ToggleButton("Button");
		final ToggleButton checkboxToggleButton = new ToggleButton("CheckBox");
		final ToggleButton radioToggleButton = new ToggleButton("Radio");
		final ToggleButton toggleButtonToggleButton = new ToggleButton("ToggleButton");

		final ToggleButton absolutePanelToggleButton = new ToggleButton("AbsolutePanel");
		final ToggleButton captionPanelToggleButton = new ToggleButton("CaptionPanel");
		final ToggleButton flowPanelToggleButton = new ToggleButton("FlowPanel");
		final ToggleButton focusPanelToggleButton = new ToggleButton("FocusPanel");
		final ToggleButton horizontalPanelToggleButton = new ToggleButton("HorizontalPanel");
		final ToggleButton verticalPanelToggleButton = new ToggleButton("VerticalPanel");
		final ToggleButton scrollPanelToggleButton = new ToggleButton("ScrollPanel");

		VerticalPanel widgetsVP = new VerticalPanel();
		widgetsVP.add(labelToggleButton);
		widgetsVP.add(textboxToggleButton);
		widgetsVP.add(buttonToggleButton);
		widgetsVP.add(checkboxToggleButton);
		widgetsVP.add(radioToggleButton);
		widgetsVP.add(toggleButtonToggleButton);

		VerticalPanel panelsVP = new VerticalPanel();
		panelsVP.add(absolutePanelToggleButton);
		panelsVP.add(captionPanelToggleButton);
		panelsVP.add(flowPanelToggleButton);
		panelsVP.add(focusPanelToggleButton);
		panelsVP.add(horizontalPanelToggleButton);
		panelsVP.add(verticalPanelToggleButton);
		panelsVP.add(scrollPanelToggleButton);

		stackPanel.add(widgetsVP, "Widgets", false);
		stackPanel.add(panelsVP, "Panels", false);

		// Put all togglebuttons in a group
		widgetPalette = new ToggleButtonGroup();
		for(int i = 0 ; i < widgetsVP.getWidgetCount() ; i ++) {
			widgetPalette.add((ToggleButton)widgetsVP.getWidget(i));
		}
		for(int i = 0 ; i < panelsVP.getWidgetCount() ; i ++) {
			widgetPalette.add((ToggleButton)panelsVP.getWidget(i));
		}

		this.widgetPalette.addSelectionHandler(new SelectionHandler<ToggleButton>() {
			@Override
			public void onSelection(SelectionEvent<ToggleButton> event) {
				ToggleButton selectedButton = event.getSelectedItem();
				if(selectedButton != null) {
					mouseInteractionHandlerManager.setInteractionMode(InteractionMode.ADD_NEW);
				}
				else{
					mouseInteractionHandlerManager.setInteractionMode(InteractionMode.SELECT);
				}
			}
		});

		// Defines the new widgets handler
		this.newWidgetsHandler = new NewObjectsHandler<Widget>() {
			private int newLabelIndex = 1;
			private int newTextBoxIndex = 1;
			private int newButtonIndex = 1;
			private int newRadioIndex = 1;
			private int newCheckBoxIndex = 1;
			private int newToggleButtonIndex = 1;

			private int newAbsolutePanelIndex = 1;
			private int newCaptionPanelIndex = 1;
			private int newFlowPanelIndex = 1;
			private int newFocusPanelIndex = 1;
			private int newHorizontalPanelIndex = 1;
			private int newVerticalPanelIndex = 1;
			private int newScrollPanelIndex = 1;

			@Override
			public Widget getNewObject() {
				if(widgetPalette.getActiveButton() != null){
					if(widgetPalette.getActiveButton() == labelToggleButton){
						Label newWidget = new Label("Label " + newLabelIndex);
						newWidget.setSize("100px", "20px");
						newLabelIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == textboxToggleButton){
						TextBox newWidget = new TextBox();
						newWidget.setText("TextBox " + newTextBoxIndex);
						newWidget.setSize("100px", "20px");
						newTextBoxIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == buttonToggleButton){
						Button newWidget = new Button();
						newWidget.setText("Button " + newButtonIndex);
						newWidget.setSize("100px", "20px");
						newButtonIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == checkboxToggleButton){
						CheckBox newWidget = new CheckBox("CheckBox " + newCheckBoxIndex);
						newWidget.setSize("100px", "20px");
						newCheckBoxIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == radioToggleButton){
						RadioButton newWidget = new RadioButton("Radio " + newRadioIndex, "Radio " + newRadioIndex);
						newWidget.setSize("100px", "20px");
						newRadioIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == toggleButtonToggleButton){
						ToggleButton newWidget = new ToggleButton("ToggleButton " + newToggleButtonIndex);
						newWidget.setSize("100px", "20px");
						newToggleButtonIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == absolutePanelToggleButton){
						AbsolutePanel newWidget = new AbsolutePanel();
						newWidget.setSize("100px", "100px");
						/*newWidget.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);
						newWidget.getElement().getStyle().setBorderWidth(1, Unit.PX);
						newWidget.getElement().getStyle().setBorderColor("#000000");*/
						newAbsolutePanelIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == captionPanelToggleButton){
						CaptionPanel newWidget = new CaptionPanel("CaptionPanel " + newCaptionPanelIndex);
						newWidget.setSize("150px", "150px");
						newCaptionPanelIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == flowPanelToggleButton){
						FlowPanel newWidget = new FlowPanel();
						newWidget.setSize("100px", "100px");
						newFlowPanelIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == focusPanelToggleButton){
						FocusPanel newWidget = new FocusPanel();
						newWidget.setSize("100px", "100px");
						newFocusPanelIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == horizontalPanelToggleButton){
						HorizontalPanel newWidget = new HorizontalPanel();
						newWidget.setSize("100px", "100px");
						newHorizontalPanelIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == verticalPanelToggleButton){
						VerticalPanel newWidget = new VerticalPanel();
						newWidget.setSize("100px", "100px");
						newVerticalPanelIndex ++;
						return newWidget;
					}
					else if(widgetPalette.getActiveButton() == scrollPanelToggleButton){
						ScrollPanel newWidget = new ScrollPanel();
						newWidget.setSize("100px", "100px");
						newScrollPanelIndex ++;
						return newWidget;
					}
				}
				return null;
			}
		};

		CaptionPanel captionPanel = new CaptionPanel("Palette");
		captionPanel.add(stackPanel);
		return captionPanel;
	}
}
